package physicalobject;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.geom.Point2D;
import main.Simulation;

/**
 * @author Robert C. Duvall
 * Edited by:
 * Patrick Royal - par24
 * Michele Reshef - mr148
 */
public abstract class Connector {
    /**
     * Spring color is white for if its length is near the rest length.
     */
    public static final double MIN_LENGTH = 0.1;
    protected Mass myStart;
    protected Mass myEnd;
    protected double myLength;
    protected double myK;

    /**
     * Constructor for spring.
     * @param start the mass on one end of the spring
     * @param end the mass on the other end of the spring
     * @param length the rest length of the spring
     * @param kVal the "springiness" of the spring
     * @param amp the amplitude of the muscle (0 for normal springs)
     */
    public Connector (final Mass start, final Mass end, final double length,
            final double kVal) {
        myStart = start;
        myEnd = end;
        myLength = length;
        myK = kVal;
    }

    /**
     * Paints the spring. The spring will be white if it is
     * (approximately) rest length, blue if it is being compressed,
     * or red if it is being stretched.
     * @param pen used to draw the line
     */
    public void paint (Graphics2D pen) {
        int xStart = (int) myStart.getCenter().getX();
        int yStart = (int) myStart.getCenter().getY();
        int xEnd = (int) myEnd.getCenter().getX();
        int yEnd = (int) myEnd.getCenter().getY();
        double dx = xStart - xEnd;
        double dy = yStart - yEnd;
        double len = Math.sqrt(dx * dx + dy * dy) - myLength;
        if (Math.abs(len) < MIN_LENGTH) {
            pen.setColor(Color.BLACK);
        }
        else if (len < 0.0) {
            pen.setColor(Color.BLUE);
        }
        else {
            pen.setColor(Color.RED);
        }

        pen.drawLine(xStart, yStart, xEnd, yEnd);
    }

    public abstract double getLength(double timeElapsed);

    /**
     * Updates the location of the spring every frame. The force
     * is calculated using Hooke's law as well as the amplitude of the
     * spring's muscle (0 for non-m uscles).
     * @param canvas the background upon which the spring is moved
     * @param dt the length of one frame, in seconds
     * @param timeElapsed the total number of frames that have taken place
     *        (used to make the muscle force harmonic)
     */
    public void update (Simulation canvas, double dt, double timeElapsed) {
        Point2D start = myStart.getCenter();
        Point2D end = myEnd.getCenter();
        double dx = start.getX() - end.getX();
        double dy = start.getY() - end.getY();
        double tempLength = getLength(timeElapsed);
        // apply hooke's law to each attached mass
        Force f = new Force(Force.angleBetween(dx, dy), myK
                * (tempLength - Force.distanceBetween(dx, dy)));
        myStart.applyForce(f);
        f.negate();
        myEnd.applyForce(f);
    }
}
